﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using Wolfbyte.Core.Data;
using Wolfbyte.Core;

namespace Wolfbyte.Core.UnitOfWork
{
    public abstract class UnitOfWorkApplication : HttpApplication
    {
        protected abstract IFactory<IUnitOfWork> UnitOfWorkFactory { get; }

        private IFactory<IUnitOfWork> cachedFactory;
        private IFactory<IUnitOfWork> CachedFactory
        {
            get
            {
                return cachedFactory ??
                    (
                        cachedFactory = new OnePerLocalContextFactory<IUnitOfWork>(UnitOfWorkFactory)
                    );
            }
        }

        public IUnitOfWork CurrentUnitOfWork
        {
            get
            {
                return CachedFactory.Create();
            }
        }

        public static UnitOfWorkApplication CurrentApplication
        {
            get
            {
                return HttpContext.Current.ApplicationInstance as UnitOfWorkApplication;
            }
        }

        public UnitOfWorkApplication()
        {
        }

        public override void Init()
        {
            base.Init();
            PreRequestHandlerExecute += UnitOfWorkApplication_BeginRequest;
            PostRequestHandlerExecute += UnitOfWorkApplication_EndRequest;
            Error += UnitOfWorkApplication_Error;
        }

        void UnitOfWorkApplication_Error(object sender, EventArgs e)
        {
            CurrentUnitOfWork.Stop();
            CurrentUnitOfWork.Dispose();
        }

        void UnitOfWorkApplication_BeginRequest(object sender, EventArgs e)
        {
            CurrentUnitOfWork.Start();
        }

        void UnitOfWorkApplication_EndRequest(object sender, EventArgs e)
        {
            CurrentUnitOfWork.Save();
            CurrentUnitOfWork.Stop();
            CurrentUnitOfWork.Dispose();
        }

        public override void Dispose()
        {
            PreRequestHandlerExecute -= UnitOfWorkApplication_BeginRequest;
            PostRequestHandlerExecute -= UnitOfWorkApplication_EndRequest;
            Error -= UnitOfWorkApplication_Error;
            base.Dispose();
        }
    }
}
